#define ds1302_sec_add        0x80    //秒数据地址
#define ds1302_min_add        0x82    //分数据地址
#define ds1302_hour_add       0x84    //时数据地址
#define ds1302_day_add        0x86    //日数据地址
#define ds1302_month_add      0x88    //月数据地址
#define ds1302_week_add       0x8a    //星期数据地址
#define ds1302_year_add       0x8c    //年数据地址
#define ds1302_control_add    0x8e    //控制数据地址
#define ds1302_charger_add    0x90    //充电       
#define ds1302_clkburst_add   0xbe

#define CLK 2
#define SDA 3
#define RST 4
#define CLK_L digitalWrite(CLK,LOW)
#define CLK_H digitalWrite(CLK,HIGH)
#define SDA_L digitalWrite(SDA,LOW)
#define SDA_H digitalWrite(SDA,HIGH)
#define SDA_R digitalRead(SDA)
#define SDA_SR  pinMode(SDA,INPUT)
#define SDA_SW  pinMode(SDA,OUTPUT)
#define RST_L digitalWrite(RST,LOW)
#define RST_H digitalWrite(RST,HIGH)

typedef struct    //第五种
{
    uint8_t year;
    uint8_t month;
    uint8_t day;
    uint8_t hour;
    uint8_t min;
    uint8_t sec;
    uint8_t week;
}timer_t;
timer_t timer{0x18,0x04,0x25,0x19,0x43,0x55,0x03};
void setup() {
  pinMode(CLK,OUTPUT);
  pinMode(SDA,OUTPUT);
  pinMode(RST,OUTPUT);
  ds1302_init();
  ds1302_write_time();
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
timer_t  t=ds1302_read_time();
Serial.print("20");
Serial.print(t.year);
Serial.print("/");
if(t.month<10) Serial.print("0");
Serial.print(t.month);
Serial.print("/");
if(t.day<10) Serial.print("0");
Serial.print(t.day);
Serial.print("  ");
if(t.hour<10) Serial.print("0");
Serial.print(t.hour);
Serial.print(":");
if(t.min<10) Serial.print("0");
Serial.print(t.min);
Serial.print(":");
if(t.sec<10) Serial.print("0");
Serial.print(t.sec);
Serial.print(" week");
Serial.print(t.week);
Serial.print("\r\n");
delay(990);
}

//DS1302初始化函数
void ds1302_init(void) 
{
  RST_L;      //RST脚置低
  CLK_L;      //SCK脚置低
}
void ds1302_write_byte(uint8_t addr, uint8_t d) 
{
  uint8_t i;
  RST_H;          //启动DS1302总线  
  addr = addr & 0xFE;   //最低位置零，寄存器0位为0时写，为1时读
  SDA_SW;
  for (i = 0; i < 8; i ++) {  //写入目标地址：addr
    if (addr & 0x01) SDA_H;
    else             SDA_L;  
    CLK_H;      
    CLK_L;
    addr = addr >> 1;
    } 
  //写入数据：d
  for (i = 0; i < 8; i ++) {  //写入目标地址：addr
    if (d & 0x01)    SDA_H;
    else             SDA_L;  
    CLK_H;      
    CLK_L;
    d = d >> 1;
    } 
  RST_L;    //停止DS1302总线
}
uint8_t ds1302_read_byte(uint8_t addr) {

  uint8_t i,temp; 
  RST_H;          //启动DS1302总线
  //写入目标地址：addr
  SDA_SW;
  addr = addr | 0x01;    //最低位置高，寄存器0位为0时写，为1时读
   for (i = 0; i < 8; i ++) {  //写入目标地址：addr
    if (addr & 0x01) SDA_H;
    else             SDA_L;  
    CLK_H;      
    CLK_L;
    addr = addr >> 1;
    } 
  //输出数据：temp
  SDA_SR;
  for (i = 0; i < 8; i ++) {
    temp = temp >> 1;
    if (SDA_R)       temp |= 0x80;
    else             temp &= 0x7F;
    CLK_H;      
    CLK_L;
    } 
  RST_L;          //停止DS1302总线
  return temp;
}

//向DS302写入时钟数据
void ds1302_write_time(void) 
{
  ds1302_write_byte(ds1302_control_add,0x00);     //关闭写保护 
  ds1302_write_byte(ds1302_sec_add,0x80);       //暂停时钟 
  ds1302_write_byte(ds1302_charger_add,0xa9);     //涓流充电 
  ds1302_write_byte(ds1302_year_add, timer.year);   //年 
  ds1302_write_byte(ds1302_month_add,timer.month);  //月 
  ds1302_write_byte(ds1302_day_add,  timer.day);   //日 
  ds1302_write_byte(ds1302_hour_add, timer.hour);   //时 
  ds1302_write_byte(ds1302_min_add,  timer.min);    //分
  ds1302_write_byte(ds1302_sec_add,  timer.sec);    //秒
  ds1302_write_byte(ds1302_week_add, timer.week);    //周 
  ds1302_write_byte(ds1302_control_add,0x80);      //打开写保护     
}
//从DS302读出时钟数据
timer_t ds1302_read_time(void)  
{
  timer_t t;
  timer.year= ds1302_read_byte(ds1302_year_add);    //年 
  timer.month=ds1302_read_byte(ds1302_month_add);   //月 
  timer.day=  ds1302_read_byte(ds1302_day_add);     //日 
  timer.hour= ds1302_read_byte(ds1302_hour_add);    //时 
  timer.min=  ds1302_read_byte(ds1302_min_add);      //分 
  timer.sec= (ds1302_read_byte(ds1302_sec_add))&0x7f;//秒，屏蔽秒的第7位，避免超出59
  timer.week= ds1302_read_byte(ds1302_week_add);     //周   
    
  t.year=((timer.year>>4)*10)   + (timer.year&0x0f);
  t.month=((timer.month>>4)*10) + (timer.month&0x0f);
  t.day=((timer.day>>4)*10)     + (timer.day&0x0f);
  t.hour=((timer.hour>>4)*10)   + (timer.hour&0x0f);
  t.min=((timer.min>>4)*10)     + (timer.min&0x0f);
  t.sec=((timer.sec>>4)*10)     + (timer.sec&0x0f);
  t.week=((timer.week>>4)*10)   + (timer.week&0x0f);
  return t;
}

